#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/5/9 13:34
# @Author : 闫峰
# @File    : listing_filter_9058.py
import datetime
from datetime import datetime, timedelta
import json
from decimal import Decimal
from typing import List

import requests

from apps.zhcxkj_center_product.prod.views.get_sku_goor_num_all import Inventory
from common.setting import ensure_path_sep
from utils.mysqlUtils.db_pool import Database
import os
import threading
import time
from common.setting import ensure_path_sep
from utils.logging_tool.log_control import LogHandler
from utils.mysqlUtils.db_pool import Database
from utils.mysqlUtils.mongodb_utils import MongoDBLink

current_path = os.path.abspath(__file__)
current_dir = os.path.dirname(current_path)
path_list = current_path.split("\\")
dis_path = "\\".join(path_list[-2:-1])


def remove_file(info_path):
    if os.path.exists(info_path):
        os.remove(info_path)
    else:
        print(f"{info_path} 不存在")


info_path = ensure_path_sep(f"\\logs\\info-{dis_path}{time.time()}")
error_path = ensure_path_sep(f"\\logs\\\error-{dis_path}{time.time()}.log")
warning_path = ensure_path_sep(f"\\logs\\warning-{dis_path}{time.time()}.log")
remove_file(info_path)
remove_file(error_path)
remove_file(warning_path)
INFO = LogHandler(info_path, level='info')
ERROR = LogHandler(error_path, level='error')
WARNING = LogHandler(warning_path, level='warning')


class SkuFilter:
    """
    allegro listing 分级策略
    涉及表 t_allegro_listing_
    """
    zhcxkj_center_listing_comprehensive = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"),
                                                   "test_jdw_database")
    zhcxkj_center_strategy_comprehensive = Database(ensure_path_sep("\\config\\shopeev2_config.yaml.bak"),
                                                    "test_jdw_database")
    # 定义mongodb
    t_listing_price_aliexpress = MongoDBLink(
        uri='mongodb://admin:Zhcx?2021@10.158.158.29:27017/?authSource=admin',
        dbname='test_zhcxkj_java_center', coll_name='t_listing_price_aliexpress')

    def __init__(self, listing_template_id):

        self.listing_template_id = listing_template_id
        t_allegro_listing_template_detail = f"t_allegro_listing_template_detail_{listing_template_id}"
        self.t_allegro_listing_template_detail = MongoDBLink(
            uri='mongodb://admin:Zhcx?2021@10.158.158.29:27017/?authSource=admin',
            dbname='test_zhcxkj_java_center', coll_name=t_allegro_listing_template_detail)
        """
    
        """

        # 查询策略条件
        get_strategy_conditions = """
        SELECT 
            a.is_enabled,
            a.option_type,  -- '模板类型（ 1-自动补货 2-半托升级 3-智能刊登 4-自动下架）',
            a.business_type, -- '商品类型（速卖通：0-POP商品 2-全托管商品 ）',
            b.rule_code, -- '规则类型（规则类型编码，依据编码来选用处理器）',
            b.execute_type, -- 规则执行类型
            b.filter_val, -- 规则值
            b.filter_min_val, -- 最小值
            b.filter_max_val, -- 最大值
            b.filter_express -- 规则表达式
        FROM test_zhcxkj_center_strategy_comprehensive.t_listing_template_aliexpress a
        LEFT JOIN test_zhcxkj_center_strategy_comprehensive.t_listing_template_rule_aliexpress b on a.id=b.template_id
        WHERE a.id= %s
        and a.is_enabled=1
        """
        strategy_conditions = self.zhcxkj_center_strategy_comprehensive.fetch_all_tuple(get_strategy_conditions,
                                                                                        (self.listing_template_id,))
        if not len(strategy_conditions):
            raise Exception("未查询到过滤模版")
        if not strategy_conditions[0][0]:
            raise Exception("模版未启用")
        # 查询类目列表
        get_category_list = """
        SELECT c.import_val
        FROM test_zhcxkj_center_strategy_comprehensive.t_listing_template_aliexpress a
        LEFT JOIN test_zhcxkj_center_strategy_comprehensive.t_import_filter_aliexpress c on a.id=c.import_id
        WHERE a.id= %s
        """
        category_list = self.zhcxkj_center_strategy_comprehensive.fetch_all_tuple(get_category_list,
                                                                                  (self.listing_template_id,))
        if not len(category_list):
            self.category_list = []
        self.category_list = list(map(lambda x: x[0], category_list))
        self.option_type = strategy_conditions[0][1]
        self.business_type = strategy_conditions[0][2]
        self.rule_code = strategy_conditions[0][3]
        # 定义规则dict
        # {rule_code:(b.execute_type, b.filter_val, b.filter_min_val, b.filter_max_val, filter_express)}
        """
        product_type
        product_status
        platform_category
        publish_time
        listing_sales_volume
        sku_sales_volume
        pop_choice_product
        variant_type
        regional_pricing
        market_picture
        """
        self.rule_code_dict = {item[3]: (item[4], item[5], item[6], item[7], item[8]) for item in strategy_conditions}
        self.filter_express_mapping = {
            "0": None,
            "1": 7,
            "2": 15,
            "3": 30,
            "4": 60,
            "5": 90
        }
        print()

    def sku_filter(self, source_id):
        """
        商品类型 pop  -- product_type
        商品状态 已上架 已下架  status  '状态 0-异常状态 1-上架 2-下架 3-审核中 4-审核不通过 5-客服删除(一般被6囊括) 6-已删除',  --product_status
        平台分类 多选  pf_category_id  --platform_category
        上架时间  时间范围 天数范围  first_publish_time  -- publish_time
        平台listing销量 可筛选：总销量、7天销量、15天销量、30天销量、60天销量、90天销量
        平台SKU销量 可筛选：总销量、7天销量、15天销量、30天销量、60天销量、90天销量
        半托管商品  是 否 pop_type   '托管类型，0-pop，1-半托管,2-全托管',    -- pop_choice_product
        单/多变体 单选：单体、多变体  has_variant '是否有变体 0否 1是',   -- variant_type
        区域化定价  单选：有、无    t_listing_price_aliexpress 集合   --regional_pricing
        营销图 单选：有、无 has_market_picture  '是否有营销图 0否 1是',  --market_picture
        :param source_id:
        :return:
        """
        dev = 'test_'
        expect_item_id_total = set()

        sql1 = f"""
        SELECT id,status,pf_category_id,first_publish_time,pop_type,has_variant,has_market_picture,pf_item_id
        FROM {dev}zhcxkj_center_listing_comprehensive.t_aliexpress_listing
        WHERE id > %s
        and source_id in %s
        and status= {int(self.rule_code_dict.get('product_status')[1])}
        and pop_type in {tuple(self.rule_code_dict.get('product_type')[1])}
        AND is_deleted=0
        ORDER BY id 
        LIMIT 1000
        """
        id_index = 0
        source_sku_set_total = set()
        count_num = 0
        while True:
            data_list = self.zhcxkj_center_listing_comprehensive.fetch_all_tuple(sql1, (id_index, source_id))
            if not len(data_list):
                # 查询不到数据 退出循环
                break
            id_index = data_list[-1][0]
            data_set = set(data_list)
            count_num += len(data_set)
            print(f"遍历{count_num}个\tsource_sku_set_total总数 {len(source_sku_set_total)}个")
            if not data_set:
                continue
            # 平台分类条件过滤
            if self.rule_code_dict.get('platform_category'):
                data_set = self.filter_category(data_set)
            if not data_set:
                continue
            # 上架时间条件过滤
            if self.rule_code_dict.get('publish_time'):
                data_set = self.filter_publist_time(data_set)
            if not data_set:
                continue
            # 是否多变体条件过滤
            if self.rule_code_dict.get('variant_type'):
                data_set = self.filter_has_variant(data_set)
            if not data_set:
                continue
            # 是否营销图条件过滤
            if self.rule_code_dict.get('market_picture'):
                data_set = self.filter_has_market_picture(data_set)
            if not data_set:
                continue

            #转换为变体维度
            get_has_variant_list = self.data_set_to_t_aliexpress_listing_sku(dev,data_set)
            if not get_has_variant_list:
                continue

            # sku销量条件过滤  变体级
            if self.rule_code_dict.get('sku_sales_volume'):
                get_has_variant_list = self.sku_sales_filter(get_has_variant_list)
            if not get_has_variant_list:
                continue
            # 平台listing销量条件过滤 变体级
            if self.rule_code_dict.get('listing_sales_volume'):
                get_has_variant_list = self.platform_sku_sales_filter(get_has_variant_list)
            if not get_has_variant_list:
                continue
            # 区域化定价条件过滤  变体级
            if self.rule_code_dict.get('regional_pricing'):
                get_has_variant_list = self.filter_regional_pricing(source_id, get_has_variant_list)
            if not get_has_variant_list:
                continue

            get_has_variant_list= set(map(lambda x:x[0],get_has_variant_list))

            source_sku_set_total |= set(get_has_variant_list)
        if not source_sku_set_total:
            ERROR.logger.error(f"最终过滤结果数为0")
            return
        ERROR.logger.error(f"最终过滤结果数为{source_sku_set_total}")
        ERROR.logger.error(f"最终过滤结果数为{len(source_sku_set_total)}")
        actual_offer_id_set = self.get_actual_offer_id_set(self.listing_template_id, source_id)
        if source_sku_set_total != actual_offer_id_set:
            ERROR.logger.error(f"")

    def get_actual_offer_id_set(self, listing_template_id, source_id):
        actual_offer_id_set = set()
        # 获取最小的ObjectId
        filters_ObjectId = {
            "$and": [
                {"listingTemplateId": listing_template_id},
                {"sourceId": source_id}
            ]
        }
        projection1 = {"offerId": 1, "_id": 1}
        res_id_index = self.t_allegro_listing_template_detail.select_skip_projection_limit(filters_ObjectId,
                                                                                           projection1, "_id", 1)
        if not len(res_id_index):
            return set()
        offer_id_start = res_id_index[0].get('offerId')
        _id_index = res_id_index[0]['_id']
        while True:
            filters_ObjectId = {
                "$and": [
                    {"listingTemplateId": listing_template_id},
                    {"sourceId": source_id},
                    {"_id": {"$gt": _id_index}}
                ]
            }
            # filter_sql = {"listingTemplateId": listing_template_id, "sourceId":source_id,"_id": {"$gte": _id_index }}
            field_ = {"offerId": 1, "_id": 1}

            actual_offer_id_list = self.t_allegro_listing_template_detail.select_skip_projection_limit(filters_ObjectId,
                                                                                                       field_, "_id",
                                                                                                       1000)
            if not len(actual_offer_id_list):
                break
            _id_index = actual_offer_id_list[-1].get('_id')
            actual_offer_id_set |= set(map(lambda x: x['offerId'], actual_offer_id_list))
        actual_offer_id_set.add(offer_id_start)

        return actual_offer_id_set

    def sku_sales_filter(self, get_has_variant_list):

        sku_list = list(map(lambda x: x[2], get_has_variant_list))
        #   根据策略规则获取销量
        if self.rule_code_dict.get('sku_sales_volume')[4] == "0":
            sku_sale_recent_days = None
        else:
            sku_sale_recent_days = self.filter_express_mapping.get(self.rule_code_dict.get('sku_sales_volume')[4])

        # 得到sku 销量字典
        sales_dict = self.get_platform_sales(sku_list, 57, sku_sale_recent_days)
        # 进行sku销量拼装
        get_has_variant_list1 = tuple(map(lambda x: (x[0], x[1], x[2], sales_dict.get(x[2])), get_has_variant_list))
        # 匹配策略
        get_has_variant_list = set(filter(lambda x: int(self.rule_code_dict.get('sku_sales_volume')[2]) <= x[3] <= int(
            self.rule_code_dict.get('sku_sales_volume')[3]), get_has_variant_list1))
        filter_has_variant_list = set(get_has_variant_list1) - get_has_variant_list
        INFO.logger.info(f"SKU销量过滤了{set(map(lambda x: x[1], filter_has_variant_list))}")
        return get_has_variant_list

    def platform_sku_sales_filter(self, get_has_variant_list):
        source_sku_list = list(map(lambda x: x[1], get_has_variant_list))
        #   根据策略规则获取销量
        if self.rule_code_dict.get('listing_sales_volume')[4] == "0":
            sku_sale_recent_days = None
        else:
            sku_sale_recent_days = self.filter_express_mapping.get(self.rule_code_dict.get('listing_sales_volume')[4])
        # 得到平台渠道sku销量字典
        sales_dict = self.get_source_sku_sales(57, source_sku_list, sku_sale_recent_days)
        # 进行渠道sku销量拼装
        # get_has_variant_list1 = tuple(
        #     map(lambda x: (x[0], x[1], x[2], x[3], sales_dict.get(x[1])), get_has_variant_list))
        get_has_variant_list1 = tuple(
            map(lambda x: (x[0], x[1], x[2], sales_dict.get(x[1])), get_has_variant_list))
        # # 匹配策略
        # get_has_variant_list = set(
        #     filter(lambda x: int(self.rule_code_dict.get('listing_sales_volume')[2]) <= x[4] <= int(
        #         self.rule_code_dict.get('listing_sales_volume')[3]), get_has_variant_list1))
        get_has_variant_list = set(
            filter(lambda x: int(self.rule_code_dict.get('listing_sales_volume')[2]) <= x[3] <= int(
                self.rule_code_dict.get('listing_sales_volume')[3]), get_has_variant_list1))

        filter_has_variant_list = set(get_has_variant_list1) - get_has_variant_list
        INFO.logger.info(f"平台渠道SKU销量过滤了{set(map(lambda x: x[1], filter_has_variant_list))}")
        return get_has_variant_list

    def get_platform_sales(self, sku_list: list[str], orderSourceType, sku_sales_days):

        sku_list = list(set(sku_list))
        url = """https://api-dw.zhcxkj.com/dw/erp/salesvolume/platform/salessku"""
        if orderSourceType != "all":
            param = {
                "input": {
                    "customerId": 1,
                    "orderSourceType": orderSourceType,
                    "skus": sku_list,
                    "days": sku_sales_days
                }
            }
        else:
            param = {
                "input": {
                    "customerId": 1,
                    "orderSourceType": None,
                    "skus": sku_list,
                    "days": sku_sales_days
                }
            }
        hearders = {
            "Content-Type": "application/json",
            "Authorization": "Basic aXJvYm90Ym94OmkxcjVvOEJvdGJveA==",
        }

        res = requests.post(url=url, headers=hearders, json=param)
        sales = {}
        if isinstance(orderSourceType, int):
            for data in res.json().get('data'):
                if data.get('orderSourceType') == orderSourceType:
                    if data["sku"] not in sales:
                        sales[data["sku"]] = data["salesVolume"]
                    else:
                        sales[data["sku"]] += data["salesVolume"]
            return sales
        else:
            for data in res.json().get('data'):
                if data["sku"] not in sales:
                    sales[data["sku"]] = data["salesVolume"]
                else:
                    sales[data["sku"]] += data["salesVolume"]
            return sales


    def get_source_sku_sales(self, orderSourceType: int, orderSourceSkus: List[str], days):
        """

        :param orderSourceType:
        :param orderSourceSkus:
        :param days: 总销量传None  其他天数传对应的值
        :return:
        """
        url = "https://api-dw.zhcxkj.com/dw/erp/salesvolume/platform/ordersourcesku"
        data = {
            "input": {
                "customerId": 1,
                "orderSourceSkus": orderSourceSkus,
                "orderSourceType": orderSourceType,
                "days": days
            }
        }
        headers = {
            "Authorization": "Basic aXJvYm90Ym94OmkxcjVvOEJvdGJveA==",
        }
        res = requests.post(url=url, headers=headers, json=data)
        data = res.json().get('data')
        # {"":""."":""}转化为字典形式
        data = {item.get('orderSourceSku'): item.get('salesVolume') for item in data}
        return data

    def filter_category(self, data_set):
        origin_data_set = data_set
        data_set = set(filter(lambda x: str(x[2]) in self.category_list, data_set))
        INFO.logger.info(f"平台分类条件过滤了{list(map(lambda x: x[7], origin_data_set - data_set))}")
        return data_set

    def filter_publist_time(self, data_set):
        origin_data_set = data_set
        if self.rule_code_dict['publish_time'][4] == "6":
            left = datetime.strptime(self.rule_code_dict['publish_time'][2], "%Y-%m-%d %H:%M:%S")
            right = datetime.strptime(self.rule_code_dict['publish_time'][3], "%Y-%m-%d %H:%M:%S")
        elif self.rule_code_dict['publish_time'][4] == "7":
            left = datetime.today()-timedelta(days=int(self.rule_code_dict['publish_time'][3]))
            right = datetime.today()-timedelta(days=int(self.rule_code_dict['publish_time'][2]))
        data_set = set(filter(lambda x: left <= x[3] <= right, data_set))
        INFO.logger.info(f"刊登时间条件过滤了{list(map(lambda x: x[7], origin_data_set - data_set))}")
        return data_set

    @staticmethod
    def batch_list(input_list, batch_size):
        """
        将一个列表分成指定大小的多个批次。

        :param input_list: 要分批的原始列表。
        :param batch_size: 每个批次的元素数量。
        :return: 分批后的列表，每个批次是一个子列表。
        """
        input_list = list(input_list)
        batches = []
        for i in range(0, len(input_list), batch_size):
            batch = input_list[i:i + batch_size]
            batches.append(batch)
        return batches

    def filter_has_variant(self, data_set):
        origin_data_set = data_set
        # elif self.rule_code_dict['publish_time'][4] == 7:
        data_set = set(filter(lambda x: x[5] == int(self.rule_code_dict['variant_type'][1]), data_set))
        INFO.logger.info(f"是否多变体条件过滤了{list(map(lambda x: x[7], origin_data_set - data_set))}")
        return data_set

    def filter_has_market_picture(self, data_set):
        origin_data_set = data_set
        # elif self.rule_code_dict['publish_time'][4] == 7:
        data_set = set(filter(lambda x: x[6] == int(self.rule_code_dict['market_picture'][1]), data_set))
        INFO.logger.info(f"是否营销图条件过滤了{list(map(lambda x: x[7], origin_data_set - data_set))}")
        return data_set

    def filter_regional_pricing(self, source_id, get_has_variant_list):
        # TODO:
        # 没有选 是否过滤
        pfListingId_list = list(map(lambda x: str(x[0]), get_has_variant_list))
        sourceSku_list = list(map(lambda x: x[1], get_has_variant_list))
        filters_ObjectId = {
            "$and": [
                {"sourceId": source_id},
                {"pfListingId": {"$in": pfListingId_list}},
                {"sourceSku": {"$in": sourceSku_list}},
            ]
        }

        projection1 = {"pfListingId":1,"popList": 1,"popChoiceList":1, "_id": 1}
        exist_data = self.t_listing_price_aliexpress.select(filters_ObjectId, projection1)
        exist_data = tuple(filter(lambda x: any([x.get('popList',None), x.get('popChoiceList',None)]),exist_data))
        exist_data = set(map(lambda x:x.get('pfListingId'),exist_data))
        if self.rule_code_dict.get('regional_pricing') == "0":
            return get_has_variant_list - exist_data
        return exist_data

    def data_set_to_t_aliexpress_listing_sku(self, dev,data_set):
        listing_set = set(map(lambda x: x[0], data_set))
        get_has_variant = f"""
        SELECT pf_item_id,pf_source_sku,sku
        FROM {dev}zhcxkj_center_listing_comprehensive.t_aliexpress_listing_sku
        WHERE listing_id in %s
        """
        get_has_variant_list = self.zhcxkj_center_strategy_comprehensive.fetch_all_tuple(get_has_variant,
                                                                                         (listing_set,))
        if not len(get_has_variant_list):
            return False
        return get_has_variant_list


if __name__ == '__main__':
    SkuFilter(18).sku_filter((5212,10010))
    # sku_list = [
    #   "", "10955590", "11208368", "11775539", "10970661", "10972007", "10972923", "11218320", "10991705", "11223204", "11490019"
    # ]
    #
    # res = SkuFilter(6).get_platform_sales(sku_list,57,None)
    # print()
